#pragma once
#include<iostream>
#include<ctime>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cstdarg>
#include<unistd.h>
#include<error.h>

using std::string;
using std::cout;
using std::endl;

const char* path="./log";
const int size=2048;

enum level
{
    info,   //正常消息
    comm,   //普通
    warn,   //警告
    err,    //出错
} ;

enum way
{
    tty,        //打印终端
    file,       //打印单个文件
    classfile   //分类打印进多个文件
};


//打印日志
class log
{
public:
    log(way w=file)          //默认使用文件方式打印
    :way_(w)   
    ,path_(path)
    {}
    
    void Init(way w) //修改打印方式
    {
        way_=w;
    }

    //获取字符串时间
    std::string get_time()      //获取当前时间
    {
        time_t t;
        t = time(nullptr);    //获取时间戳
        // std::cout<<"当前的时间为： "<<std::endl;
        // std::cout<<t<<std::endl;

        //时间戳转标准时间
        struct tm *stand_time=localtime(&t);
        std::string str;

        //标准时间转字符串
        std::string tmp="/";

        str+=std::to_string(stand_time->tm_year+1900)+tmp
                +std::to_string(stand_time->tm_mon+1)+tmp
                +std::to_string(stand_time->tm_mday);
        str.push_back(' ');
        tmp=":";
        str+=std::to_string(stand_time->tm_hour)+tmp+
            std::to_string(stand_time->tm_min)+tmp+
            std::to_string(stand_time->tm_sec);

        // std::cout<<str<<std::endl;
        
        return str;
    }

    std::string info_level(int info_name)     //错误等级
    {
        switch (info_name)
        {
        case info:
            /* code */
            return "info";
            break;
        
        case comm:
            return "comm";
            break;
        case warn:
            return "warn";
            break;
        case err:
            return "error";
            break;
        default:
            cout<<"输入等级错误"<<endl;
            return "!!!";
            break;
        }
    }

    //打印方式     
    void printway(int le,string log)    
    {
        switch(way_)
        {
            case tty:
                cout<<log<<endl;
                break;
            case file:
                print_file(log);
                break;
            case classfile:
                print_class(le,log);
            default:
                cout<<way_<<endl;
                break;
        }
    }

    void print_file(string log)
    {
        int fd=open(path_.c_str(),O_WRONLY|O_APPEND|O_CREAT,0664);
        if(fd<0)
        {
            perror("open");
            exit(-1);
        }
        // cout<<log<<endl;    //临时测试
        log+="\n";
        const char* l=log.c_str();

        write(fd,l,log.size());     //日志写进文件
    }

    void print_class(int le,string log)
    {
        path_+="/"+info_level(le);
       
        print_file(log);
    }

    void operator()(int le,const char* format,...)   //可变参数
    {
        char buffer[size];
        va_list args;
        va_start(args,format);
        vsnprintf(buffer,sizeof(buffer),format,args);
        va_end(args);

        
        std::string str="[";
        str+=info_level(le)+"]"+":";

        str+=get_time()+":"+buffer;

        // cout<<str<<endl;

        printway(le,str);

    }

private:
    string path_;       //打印路径
    way way_;           //打印方式
};